#!/bin/bash

# ----------------------------------------------------------------------
# | Colors                                                             |
# ----------------------------------------------------------------------

enable_color_support() {

    if [[ $COLORTERM == gnome-* && $TERM == xterm ]] \
        && infocmp gnome-256color &> /dev/null; then
        export TERM='gnome-256color'
    elif infocmp xterm-256color &> /dev/null; then
        export TERM='xterm-256color'
    fi

    if [ "$OS" == "osx" ]; then
        alias ls='ls -G' # or CLICOLOR=1

    elif [ "$OS" == "ubuntu" ]; then
        if [ -x /usr/bin/dircolors ]; then

            test -r ~/.dircolors \
                && eval "$(dircolors -b ~/.dircolors)" \
                || eval "$(dircolors -b)"

            alias dir='dir --color=auto'
            alias egrep='egrep --color=auto'
            alias fgrep='fgrep --color=auto'
            alias grep='grep --color=auto'
            alias ls='ls --color=auto'
            alias vdir='vdir --color=auto'

        fi
    fi

}

set_ls_colors() {

    # There are several different implementations of color for ls:

    # ------------------------------------------------------------------
    # | FreeBSD / OS X                                                 |
    # ------------------------------------------------------------------

    #  - `ls` displays colors if the `-G` option is passed or if
    #    the `CLICOLOR` environment variable is set
    #
    #  - the actual colors are configured through the `LSCOLORS`
    #    environment variable (built-in defaults are used if this
    #    variable is not set)

    if [ "$OS" == "osx" ]; then

        LSCOLORS=''

        LSCOLORS+='gx' # Directory
        LSCOLORS+='fx' # Symbolic link
        LSCOLORS+='cx' # Socket
        LSCOLORS+='dx' # Pipe
        LSCOLORS+='cx' # Executable
        LSCOLORS+='eg' # Block special
        LSCOLORS+='ed' # Character special
        LSCOLORS+='ab' # Executable with setuid bit set
        LSCOLORS+='ag' # Executable with setgid bit set
        LSCOLORS+='cc' # Directory writable to others, with sticky bit
        LSCOLORS+='bd' # Directory writable to others, without sticky bit

        export LSCOLORS

    # ------------------------------------------------------------------
    # | GNU                                                            |
    # ------------------------------------------------------------------

    #  - `ls` displays colors if the `--color` option is passed
    #
    #  - the actual colors are configured through the `LS_COLORS`
    #    environment variable (built-in defaults are used if this
    #    variable is not set)

    elif [ "$OS" == "ubuntu" ]; then

        LS_COLORS=''

        LS_COLORS+='no=0;39:'   # global default
        LS_COLORS+='di=0;36:'   # directory
        LS_COLORS+='ex=0;32:'   # executable file
        LS_COLORS+='fi=0;39:'   # file
        LS_COLORS+='ec=:'       # non-filename text
        LS_COLORS+='mi=1;31:'   # non-existent file pointed to by a symlink
        LS_COLORS+='ln=target:' # symbolic link
        LS_COLORS+='or=31;01'   # symbolic link pointing to a non-existent file

        export LS_COLORS

    fi
}

# ----------------------------------------------------------------------
# | Prompts                                                            |
# ----------------------------------------------------------------------

# Note: Don't break this function into smaller, more specialized ones
# as you will only pollute the global space even more (this function
# cannot be unset due to the fact that it's called every time the prompt
# string is shown)

get_git_repository_details() {

    local branchName=''
    local tmp=''

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    # Check if the current directory is in a Git repository
    [ "$(git rev-parse &>/dev/null; printf $?)" -ne 0 ] && return

    # Check if in `.git/` directory (some of the following
    # checks don't make sense/won't work in the `.git` directory)
    [ "$(git rev-parse --is-inside-git-dir)" == "true" ] && return

    # Check for uncommitted changes in the index
    if ! $(git diff --quiet --ignore-submodules --cached); then
        tmp="$tmp+";
    fi

    # Check for unstaged changes
    if ! $(git diff-files --quiet --ignore-submodules --); then
        tmp="$tmp!";
    fi

    # Check for untracked files
    if [ -n "$(git ls-files --others --exclude-standard)" ]; then
        tmp="$tmp?";
    fi

    # Check for stashed files
    if $(git rev-parse --verify refs/stash &>/dev/null); then
        tmp="$tmp$";
    fi

    [ -n "$tmp" ] && tmp=" [$tmp]"


    branchName="$( printf "$( git rev-parse --abbrev-ref HEAD 2> /dev/null \
        || git rev-parse --short HEAD 2> /dev/null \
        || printf " (unknown)" )" | tr -d "\n" )"


    printf "%s" "$1$branchName$tmp"

}

set_prompts() {

    local black='' blue='' bold='' cyan='' green='' orange='' \
          purple='' red='' reset='' white='' yellow=''

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    if [ -x /usr/bin/tput ] && tput setaf 1 &> /dev/null; then

        tput sgr0 # Reset colors

        bold=$(tput bold)
        reset=$(tput sgr0)

        # Solarized colors
        # https://github.com/altercation/solarized/tree/master/iterm2-colors-solarized#the-values

        black=$(tput setaf 0)
        blue=$(tput setaf 33)
        cyan=$(tput setaf 37)
        green=$(tput setaf 64)
        orange=$(tput setaf 166)
        purple=$(tput setaf 125)
        red=$(tput setaf 124)
        white=$(tput setaf 15)
        yellow=$(tput setaf 136)

    else

        bold=''
        reset="\e[0m"

        black="\e[1;30m"
        blue="\e[1;34m"
        cyan="\e[1;36m"
        green="\e[1;32m"
        orange="\e[1;33m"
        purple="\e[1;35m"
        red="\e[1;31m"
        white="\e[1;37m"
        yellow="\e[1;33m"

    fi

    # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    # Prompt Statement variables
    # http://ss64.com/bash/syntax-prompt.html

    # ------------------------------------------------------------------
    # | PS1 - Default interactive prompt                               |
    # ------------------------------------------------------------------

    PS1="\[\033]0;\w\007\]"         # Terminal title (set to the
                                    # current working directory)
    PS1+="\[$bold\]"
    PS1+="\[$orange\]\u"            # Username
    PS1+="\[$white\]@"
    PS1+="\[$yellow\]\h"            # Host
    PS1+="\[$white\]: "
    PS1+="\[$green\]\w"             # Working directory
    PS1+="\$(get_git_repository_details \"$white on $cyan\")"
    PS1+="\n"
    PS1+="\[$reset$white\]\$ \[$reset\]"

    export PS1

    # ------------------------------------------------------------------
    # | PS2 - Continuation interactive prompt                          |
    # ------------------------------------------------------------------

    PS2='⚡ '

    export PS2

    # ------------------------------------------------------------------
    # | PS4 - Debug prompt                                             |
    # ------------------------------------------------------------------

    # e.g:
    #
    # The GNU `date` command has the `%N` interpreted sequence while
    # other implementations don't (on OS X `gdate` can be used instead
    # of the native `date` if the `coreutils` package was installed)
    #
    # local dateCmd=""
    #
    # if [ "$(date +%N)" != "N" ] || \
    #    [ ! -x "$(command -v 'gdate')" ]; then
    #    dateCmd="date +%s.%N"
    # else
    #    dateCmd="gdate +%s.%N"
    # fi
    #
    # PS4="+$( tput cr && tput cuf 6 &&
    #          printf "$yellow %s $green%6s $reset" "$($dateCmd)" "[$LINENO]" )"
    #
    # PS4 output:
    #
    #   ++    1357074705.875970000  [123] '[' 1 == 0 ']'
    #   └──┬─┘└────┬───┘ └───┬───┘ └──┬─┘ └──────┬─────┘
    #      │       │         │        │          │
    #      │       │         │        │          └─ command
    #      │       │         │        └─ line number
    #      │       │         └─ nanoseconds
    #      │       └─ seconds since 1970-01-01 00:00:00 UTC
    #      └─ depth-level of the subshell

    PS4="+$( tput cr && tput cuf 6 && printf "%s $reset" )"

    export PS4

}

# ----------------------------------------------------------------------
# | Main                                                               |
# ----------------------------------------------------------------------

main() {
    enable_color_support
    set_ls_colors
    set_prompts
}

main

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

# Unset functions in order to not pollute the global space
unset -f enable_color_support
unset -f main
unset -f set_ls_colors
unset -f set_prompts
